package models

import (
	"context"
	"fmt"
	"github.com/cy77cc/hioshop/global"
	"github.com/google/uuid"
	"log"
	"time"
)

type Order struct {
	Model
	OrderSn        string  `json:"order_sn"`
	UserId         uint    `json:"user_id"`
	OrderStatus    uint16  `json:"order_status"`
	OfflinePay     int8    `json:"offline_pay"`
	ShippingStatus uint8   `json:"shipping_status"`
	PrintStatus    int8    `json:"print_status"`
	PayStatus      uint8   `json:"pay_status"`
	Consignee      string  `json:"consignee"`
	Country        uint8   `json:"country"`
	Province       uint8   `json:"province"`
	City           uint8   `json:"city"`
	District       uint8   `json:"district"`
	Address        string  `json:"address"`
	PrintInfo      string  `json:"print_info"`
	Mobile         string  `json:"mobile"`
	Postscript     string  `json:"postscript"`
	AdminMemo      string  `json:"admin_memo"`
	ShippingFee    float64 `json:"shipping_fee"`
	PayName        string  `json:"pay_name"`
	PayId          string  `json:"pay_id"`
	ChangePrice    float64 `json:"change_price"`
	ActualPrice    float64 `json:"actual_price"`
	OrderPrice     float64 `json:"order_price"`
	GoodsPrice     float64 `json:"goods_price"`
	AddTime        uint    `json:"add_time"`
	PayTime        uint    `json:"pay_time"`
	ShippingTime   uint    `json:"shipping_time"`
	ConfirmTime    uint    `json:"confirm_time"`
	DealdoneTime   uint    `json:"dealdone_time"`
	FreightPrice   uint    `json:"freight_price"`
	ExpressValue   float64 `json:"express_value"`
	Remark         string  `json:"remark"`
	OrderType      uint8   `json:"order_type"`
	IsDelete       uint8   `json:"is_delete"`
}

func (o Order) GetOrderCountByStatus(status []int) (count int64, err error) {
	get := global.REDIS.Get(context.Background(), fmt.Sprintf("order_count:%d", o.UserId))
	if get.Err() != nil {
		err = global.DB.Model(&Order{}).Where("order_type < 7").Where(map[string]any{
			"user_id":      o.UserId,
			"is_delete":    0,
			"order_status": status,
		}).Count(&count).Error
		err = global.REDIS.Set(context.Background(), fmt.Sprintf("order_count:%d", o.UserId), count, time.Hour).Err()
		return
	}

	count, _ = get.Int64()
	return
}

func (o Order) GetOrderListByStatus(status []int, page int, pageSize int) (list []Order, err error) {
	err = global.DB.Model(&Order{}).Where("order_type < 7").Where(map[string]any{
		"user_id":      o.UserId,
		"is_delete":    0,
		"order_status": status,
	}).Offset((page - 1) * page).Limit(pageSize).Find(&list).Error
	return
}

func (o Order) GetOrderStatusText() string {
	statusText := "待付款"
	switch o.ID {
	case 101:
		statusText = "待付款"
	case 102:
		statusText = "交易关闭"
	case 103:
		statusText = "交易关闭" //到时间系统自动取消
	case 201:
		statusText = "待发货"
	case 300:
		statusText = "待发货"
	case 301:
		statusText = "已发货"
	case 401:
		statusText = "交易成功" //到时间，未收货的系统自动收货、
	}
	return statusText
}

func (o Order) GetOrderHandleOption() map[string]bool {
	handleOption := map[string]bool{
		"cancel":        false, // 取消操作
		"delete":        false, // 删除操作
		"pay":           false, // 支付操作
		"confirm":       false, // 确认收货完成订单操作
		"cancel_refund": false,
	}
	// 订单流程：下单成功－》支付订单－》发货－》收货－》评论
	// 订单相关状态字段设计，采用单个字段表示全部的订单状态
	// 1xx表示订单取消和删除等状态：  101订单创建成功等待付款、102订单已取消、103订单已取消(自动)
	// 2xx表示订单支付状态：        201订单已付款，等待发货、202订单取消，退款中、203已退款
	// 3xx表示订单物流相关状态：     300订单待发货，301订单已发货，302用户确认收货、303系统自动收货
	// 4xx表示订单完成的状态：      401已收货已评价
	// 5xx表示订单退换货相关的状态：  501已收货，退款退货 TODO
	// 如果订单已经取消或是已完成，则可删除和再次购买
	// if (status == 101) "未付款";
	// if (status == 102) "已取消";
	// if (status == 103) "已取消(系统)";
	// if (status == 201) "已付款";
	// if (status == 300) "待发货";
	// if (status == 301) "已发货";
	// if (status == 302) "已收货";
	// if (status == 303) "已收货(系统)";
	//  TODO 设置一个定时器，自动将有些订单设为完成
	// 订单刚创建，可以取消订单，可以继续支付
	switch o.OrderStatus {
	case 101, 801:
		handleOption["cancel"] = true
		handleOption["pay"] = true
	case 201:
		handleOption["delete"] = true
	case 202:
		handleOption["cancel_refund"] = true
	case 203:
		handleOption["delete"] = true
	case 301:
		handleOption["confirm"] = true
	case 401:
		handleOption["delete"] = true
	}
	return handleOption
}

type OrderExpress struct {
	Model
	OrderId      uint   `json:"order_id"`
	ShipperId    uint   `json:"shipper_id"`
	ShipperName  string `json:"shipper_name"`
	ShipperCode  string `json:"shipper_code"`
	LogisticCode string `json:"logistic_code"`
	Traces       string `json:"traces"`
	IsFinish     uint8  `json:"is_finish"`
	RequestCount int    `json:"request_count"`
	RequestTime  int    `json:"request_time"`
	AddTime      int    `json:"add_time"`
	UpdateTime   int    `json:"update_time"`
	ExpressType  uint8  `json:"express_type"`
	RegionCode   string `json:"region_code"`
}

type OrderGoods struct {
	Id                          uint    `gorm:"primary_key;auto_increment" json:"id"`
	OrderId                     uint    `json:"order_id"`
	UserId                      uint    `json:"user_id"`
	GoodsId                     uint    `json:"goods_id"`
	GoodsName                   string  `json:"goods_name"`
	GoodsAka                    string  `json:"goods_aka"`
	ProductId                   uint    `json:"product_id"`
	Number                      uint8   `json:"number"`
	RetailPrice                 float64 `json:"retail_price"`
	GoodsSpecificationNameValue string  `json:"goods_specification_name_value"`
	GoodsSpecificationIds       string  `json:"goods_specification_ids"`
	ListPicUrl                  string  `json:"list_pic_url"`
	IsDelete                    uint8   `json:"is_delete"`
}

func (o OrderGoods) GetGoodsList() (list []OrderGoods, err error) {
	err = global.DB.Model(&OrderGoods{}).Select("id,list_pic_url,number").Where(map[string]any{
		"user_id":   o.UserId,
		"order_id":  o.OrderId,
		"is_delete": 0,
	}).Find(&list).Error
	return
}

type ExpressInfo struct {
	ShipperCode  string `json:"shipper_code"`
	ShipperName  string `json:"shipper_name"`
	LogisticCode string `json:"logistic_code"`
	IsFinish     uint8  `json:"is_finish"`
	RequestTime  int    `json:"request_time"`
	Traces       string `json:"traces"`
}

func (oe *OrderExpress) GetLatestOrderExpress() {

	err := global.DB.Model(&oe).Find(&oe).Error
	if err != nil {
		log.Println(err)
		return
	}

	//// 查询最新物流信息
	//const ExpressSerivce = think.service("express", "api"); // 引入api
	//// 调用api里的queryExpress方法 最重要
	//const latestExpressInfo = await ExpressSerivce.queryExpress(orderExpress.shipper_code, orderExpress.logistic_code);
	//const nowTime = Number.parseInt(Date.now() / 1000);
	//const updateData = {
	//request_time: nowTime,
	//	update_time: nowTime,
	//		request_count: ["EXP", "request_count+1"]
	//};
	//if (latestExpressInfo.success) {
	//returnExpressInfo.traces = latestExpressInfo.traces;
	//returnExpressInfo.is_finish = latestExpressInfo.isFinish;
	//// 查询成功则更新订单物流信息
	//updateData.traces = JSON.stringify(latestExpressInfo.traces);
	//returnExpressInfo.request_time = think.datetime(nowTime * 1000);
	//updateData.is_finish = latestExpressInfo.isFinish;
	//}
	//await this.where({
	//id: orderExpress.id
	//}).update(updateData);
	//return returnExpressInfo;
}

func generateOrderNumber() string {
	uuidStr := uuid.New().String()
	return uuidStr
}
